home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / filesyst / dosfs / dmsdosfs.000 / dmsdosfs / dmsdosfs-0.6.9b / dmsdos_ioctl.c < prev    next >
C/C++ Source or Header  |  1996-07-29  |  15KB  |  462 lines

  1. /*
  2.  
  3. linux/fs/dmsdos/dmsdos_ioctl.c
  4.  
  5. DMSDOS filesystem: special functions for further dmsdos tools
  6.  
  7. ******************************************************************************
  8. DMSDOS (Doublespace/Drivespace compressed MSDOS filesystem) for Linux
  9. written 1995,1996 by Frank Gockel
  10.  
  11.     (C) Copyright 1995,1996 by Frank Gockel
  12.  
  13. Some code of the dmsdos filesystem has been copied from the msdos filesystem
  14. so there are the following additional copyrights:
  15.  
  16.     (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
  17.     (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
  18.     (C) Copyright 1992-1995 by Linus Torvalds
  19.  
  20. The DMSDOS filesystem was inspired by the THS filesystem (a simple doublespace
  21. DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.
  22.  
  23. The DMSDOS filesystem is distributed under the Gnu General Public Licence.
  24. See file COPYING for details.
  25. ******************************************************************************
  26.  
  27. */
  28.  
  29. #include <asm/segment.h>
  30. #include <linux/errno.h>
  31. #include <linux/kernel.h>
  32. #include <linux/sched.h>
  33. #include <linux/fs.h>
  34. #include <linux/msdos_fs.h>
  35. #include <linux/dmsdos_fs.h>
  36.  
  37.  
  38. #define PRINTK(x)
  39. #define Printk(x) printk x
  40.  
  41. extern Dblsb dblsb[];
  42.  
  43. int daemon_present=0;
  44. Rwlist rwlist[LISTSIZE];
  45. int rlist=0;
  46. int wlist=0;
  47.  
  48. void dumpcache(void);
  49.  
  50. struct wait_queue * list_wait = NULL;
  51. int list_lock=0;
  52. void lock_listaccess(void)
  53. { while(list_lock)sleep_on(&list_wait);
  54.   list_lock=1;
  55. }
  56. void unlock_listaccess(void)
  57. { list_lock=0;
  58.   wake_up(&list_wait);
  59. }
  60.  
  61. int set_maxcluster(struct super_block*sb,int data,int cvfnr)
  62. { struct buffer_head*bh,*bh2;
  63.   int i;
  64.   unsigned char*pp;
  65.   unsigned long int sectors;
  66.  
  67.   if(data<2||data>dblsb[cvfnr].s_max_cluster2)return -EINVAL;
  68.   /* check if higher clusters are unused */
  69.   for(i=dblsb[cvfnr].s_max_cluster2;i>data;--i)
  70.   { if(dbl_fat_nextcluster(sb,i,cvfnr,NULL))
  71.     { printk("DMSDOS: CVF %d: set_maxcluster %d refused: cluster %d in use\n",
  72.              cvfnr+1,data,i);
  73.       return -EINVAL;
  74.     }
  75.   }
  76.   
  77.   bh=read_dbl_sector(sb,0,cvfnr);
  78.   if(bh==NULL)return -EIO;
  79.   bh2=read_dbl_sector(sb,dblsb[cvfnr].s_bootblock,cvfnr);
  80.   if(bh2==NULL)
  81.   { bh_free(sb,bh);
  82.     return -EIO;
  83.   }
  84.   
  85.   /* calculate number of sectors */
  86.   sectors=(data-1)<<4;
  87.   sectors+=dblsb[cvfnr].s_rootdiranzentry>>4;
  88.   pp=&(bh->b_data[14]);
  89.   sectors+=CHS(pp);
  90.   pp=&(bh->b_data[22]);
  91.   sectors+=CHS(pp);
  92.   bh->b_data[32]=sectors;
  93.   bh->b_data[33]=sectors>>8;
  94.   bh->b_data[34]=sectors>>16;
  95.   bh->b_data[35]=sectors>>24;
  96.   sectors+=CHS(pp);
  97.   bh2->b_data[32]=sectors;
  98.   bh2->b_data[33]=sectors>>8;
  99.   bh2->b_data[34]=sectors>>16;
  100.   bh2->b_data[35]=sectors>>24;
  101.   bh_dirty(sb,bh);
  102.   bh_dirty(sb,bh2);
  103.   bh_free(sb,bh);
  104.   bh_free(sb,bh2);
  105.   
  106.   dblsb[cvfnr].s_max_cluster=data;
  107.   
  108.   return 0;
  109. }
  110.     
  111. int dmsdos_ioctl_dir(
  112.     struct inode *dir,
  113.     struct file *filp,
  114.     unsigned int cmd,
  115.     unsigned long data)
  116. { unsigned char* idata;
  117.   int cvfnr;
  118.   struct buffer_head*bh;
  119.   int newval;
  120.   int val;
  121.   int cluster;
  122.   int entrynr;
  123.   int free_clusters,used_clusters,error_clusters;
  124.   int free_sectors,used_sectors,max_size,sector,size;
  125.   Mdfat_entry mde,dummy;
  126.   int mdfatk,mdfatd,mdfat_sumk,mdfat_sumd;
  127.   unsigned char buf[32];
  128.   unsigned char *clusterd;
  129.   int length;
  130.   int i;
  131.   int plist;
  132.   int sectors;
  133.  
  134.   if(dostest(dir))return -EINVAL;
  135.   if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  136.   else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  137.   idata=(unsigned char*)data;
  138.  
  139.   switch(cmd)    
  140.   { case DMSDOS_GET_DBLSB:
  141.       /* check dutil version number */
  142.       if(get_fs_long(idata)<DMSDOS_LOWEST_COMPATIBLE_VERSION)
  143.         return DMSDOS_VERSION|0x0f000000;
  144.       memcpy_tofs(idata,(unsigned char*)&(dblsb[cvfnr]),sizeof(Dblsb));
  145.       return DMSDOS_VERSION;
  146.     case DMSDOS_EXTRA_STATFS:
  147.       free_sectors=0;
  148.       max_size=0;  
  149.       for(sector=dblsb[cvfnr].s_datastart;sector<dblsb[cvfnr].s_dataend;
  150.           ++sector)
  151.       { if(dbl_bitfat_value(dir->i_sb,sector,cvfnr,NULL)==0)
  152.         { ++free_sectors;
  153.           size=1;
  154.           while(dbl_bitfat_value(dir->i_sb,sector+size,cvfnr,NULL)==0)++size;
  155.           if(size>max_size)max_size=size;
  156.           sector+=size-1;
  157.           free_sectors+=size-1;
  158.         }
  159.       }
  160.       used_sectors=dblsb[cvfnr].s_dataend+1-dblsb[cvfnr].s_datastart
  161.                    -free_sectors;
  162.       mdfat_sumk=0;
  163.       mdfat_sumd=0;
  164.       mdfatk=0;
  165.       mdfatd=0;
  166.       free_clusters=0;
  167.       used_clusters=0;
  168.       error_clusters=0;
  169.       for(cluster=2;cluster<=dblsb[cvfnr].s_max_cluster;++cluster)
  170.       { if(dbl_fat_nextcluster(dir->i_sb,cluster,cvfnr,NULL)!=0)
  171.         { dbl_mdfat_value(dir->i_sb,cluster,cvfnr,NULL,&mde);
  172.           /*if(mdfat&0x80000000)*/
  173.           if(mde.flags&2)
  174.           { ++used_clusters;
  175.             /*if(mdfat&0x40000000)++mdfatd; else ++mdfatk;*/
  176.             if(mde.flags&1)++mdfatd; else ++mdfatk;
  177.             mdfat_sumd+=mde.size_hi_minus_1+1;
  178.             mdfat_sumk+=mde.size_lo_minus_1+1;
  179.           }
  180.           else ++error_clusters;
  181.         }
  182.         else ++free_clusters;
  183.       }
  184.       put_fs_long(free_sectors,idata);
  185.       put_fs_long(used_sectors,idata+4);
  186.       put_fs_long(max_size,idata+8);
  187.       put_fs_long(free_clusters,idata+12);
  188.       put_fs_long(used_clusters,idata+16);
  189.       put_fs_long(error_clusters,idata+20);
  190.       put_fs_long(mdfat_sumk,idata+24);
  191.       put_fs_long(mdfat_sumd,idata+28);
  192.       put_fs_long(mdfatk,idata+32);
  193.       put_fs_long(mdfatd,idata+36);
  194.       return 0;
  195.     case DMSDOS_READ_BLOCK:
  196.       if(current->euid!=0)return -EPERM;
  197.       sector=get_fs_long(idata);
  198.       if(sector<0||sector>dblsb[cvfnr].s_dataend)return -EINVAL;
  199.       bh=read_dbl_sector(dir->i_sb,sector,cvfnr);
  200.       if(bh==NULL)return -EIO;
  201.       memcpy_tofs(idata+4,bh->b_data,SECTOR_SIZE);
  202.       bh_free(dir->i_sb,bh);
  203.       return 0;
  204.     case DMSDOS_WRITE_BLOCK:
  205.       if(current->euid!=0)return -EPERM;
  206.       sector=get_fs_long(idata);
  207.       if(sector<0||sector>dblsb[cvfnr].s_dataend)return -EINVAL;
  208.       bh=noread_dbl_sector(dir->i_sb,sector,cvfnr);
  209.       if(bh==NULL)return -EIO;
  210.       memcpy_fromfs(bh->b_data,idata+4,SECTOR_SIZE);
  211.       bh_dirty(dir->i_sb,bh);
  212.       bh_free(dir->i_sb,bh);
  213.       return 0;
  214.     case DMSDOS_READ_DIRENTRY:
  215.       if(current->euid!=0)return -EPERM;
  216.       cluster=get_fs_long(idata);
  217.       if(cluster>dblsb[cvfnr].s_max_cluster)return -EINVAL;
  218.       if(cluster<0)cluster=MSDOS_I(dir)->i_start;
  219.       entrynr=get_fs_long(idata+4);
  220.       val=read_dbl_direntry(dir->i_sb,cluster,cvfnr,entrynr,buf);
  221.       if(val<0)return val;
  222.       memcpy_tofs(idata+8,buf,32);
  223.       return 0;
  224.     case DMSDOS_WRITE_DIRENTRY:
  225.       if(current->euid!=0)return -EPERM;
  226.       cluster=get_fs_long(idata);
  227.       if(cluster>dblsb[cvfnr].s_max_cluster)return -EINVAL;
  228.       if(cluster<0)cluster=MSDOS_I(dir)->i_start;
  229.       entrynr=get_fs_long(idata+4);
  230.       val=read_dbl_direntry(dir->i_sb,cluster,cvfnr,entrynr,buf);
  231.       if(val<0)return val;
  232.       bh=read_dbl_sector(dir->i_sb,(val&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  233.       if(bh==NULL)return -EIO;
  234.       memcpy_fromfs(&(bh->b_data[32*(val&0xf)]),idata+8,32);
  235.       bh_dirty(dir->i_sb,bh);
  236.       bh_free(dir->i_sb,bh);
  237.       return 0;
  238.     case DMSDOS_READ_BITFAT:
  239.       sector=get_fs_long(idata);
  240.       if(sector<0||sector>dblsb[cvfnr].s_dataend)return -EINVAL;
  241.       val=dbl_bitfat_value(dir->i_sb,sector,cvfnr,NULL);
  242.       put_fs_long(val,idata+4);
  243.       return 0;
  244.     case DMSDOS_WRITE_BITFAT:
  245.       if(current->euid!=0)return -EPERM;
  246.       sector=get_fs_long(idata);
  247.       if(sector<0||sector>dblsb[cvfnr].s_dataend)return -EINVAL;
  248.       newval=get_fs_long(idata+4);
  249.       dbl_bitfat_value(dir->i_sb,sector,cvfnr,&newval);
  250.       return 0;
  251.     case DMSDOS_READ_MDFAT:
  252.       cluster=get_fs_long(idata);
  253.       if(cluster>dblsb[cvfnr].s_max_cluster)return -EINVAL;
  254.       dbl_mdfat_value(dir->i_sb,cluster,cvfnr,NULL,&mde);
  255.       /*put_fs_long(val,idata+4);*/
  256.       memcpy_tofs((Mdfat_entry*)get_fs_long(idata+4),&mde,sizeof(Mdfat_entry));
  257.       return 0;
  258.     case DMSDOS_WRITE_MDFAT:
  259.       if(current->euid!=0)return -EPERM;
  260.       cluster=get_fs_long(idata);
  261.       if(cluster>dblsb[cvfnr].s_max_cluster)return -EINVAL;
  262.       /*newval=get_fs_long(idata+4);*/
  263.       memcpy_fromfs(&mde,(Mdfat_entry*)get_fs_long(idata+4),sizeof(Mdfat_entry));
  264.       dbl_mdfat_value(dir->i_sb,cluster,cvfnr,&mde,&dummy);
  265.       return 0;
  266.     case DMSDOS_READ_DFAT:
  267.       cluster=get_fs_long(idata);
  268.       if(cluster>dblsb[cvfnr].s_max_cluster)return -EINVAL;
  269.       val=dbl_fat_nextcluster(dir->i_sb,cluster,cvfnr,NULL);
  270.       put_fs_long(val,idata+4);
  271.       return 0;
  272.     case DMSDOS_WRITE_DFAT:
  273.       if(current->euid!=0)return -EPERM;
  274.       cluster=get_fs_long(idata);
  275.       if(cluster>dblsb[cvfnr].s_max_cluster)return -EINVAL;
  276.       newval=get_fs_long(idata+4);
  277.       dbl_fat_nextcluster(dir->i_sb,cluster,cvfnr,&newval);
  278.       return 0;
  279.     case DMSDOS_SET_COMP:
  280.       if(current->euid!=0)return -EPERM;
  281.       dblsb[cvfnr].s_comp=data;
  282.       return 0;
  283.     case DMSDOS_SET_CF:
  284.       if(current->euid!=0)return -EPERM;
  285.       if(data>=12u)return -EINVAL;
  286.       dblsb[cvfnr].s_cfaktor=data;
  287.       return 0;
  288.     case DMSDOS_SIMPLE_CHECK:
  289.       val=simple_check(dir->i_sb,cvfnr);
  290.       put_fs_long(val,idata);
  291.       return 0;
  292.     case DMSDOS_DUMPCACHE:
  293.       dumpcache();
  294.       return 0;
  295.     case DMSDOS_D_ASK:
  296.       if(current->euid!=0)return -EPERM;
  297.       /* meldet dmsdosd an */
  298.       daemon_present=1;
  299.       /*printk("DMSDOS: D_ASK\n");*/
  300.       return 0;
  301.     case DMSDOS_D_READ:
  302.       if(current->euid!=0)return -EPERM;
  303.       lock_listaccess();
  304.       /*search next valid entry*/
  305.       for(i=LISTSIZE;i>0;--i)
  306.       { if(rwlist[rlist].flag==D_VALID)
  307.         { /* check in mdfat that cluster is actually used */
  308.           dbl_mdfat_value(dir->i_sb,rwlist[rlist].clusternr,rwlist[rlist].cvfnr,
  309.                           NULL,&mde);
  310.           if((mde.flags&3)==3)goto vr_found; /* used and uncompressed */
  311.           rwlist[rlist].flag=D_EMPTY;  /* remove - it's garbage */
  312.           /*printk("DMSDOS: D_READ: removing garbage entry cluster=%d cvf=%d\n",
  313.                  rwlist[rlist].clusternr,rwlist[rlist].cvfnr+1);
  314.           */
  315.         }
  316.         rlist=(rlist+1)&(LISTSIZE-1);
  317.       }
  318.       unlock_listaccess();
  319.       return 0;
  320.    vr_found:
  321.       cluster=rwlist[rlist].clusternr;
  322.       cvfnr=rwlist[rlist].cvfnr;
  323.       length=rwlist[rlist].length;
  324.       clusterd=MALLOC(dblsb[cvfnr].s_sectperclust*SECTOR_SIZE);
  325.       if(clusterd==NULL)
  326.       { printk("DMSDOS: ioctl: D_READ: no memory!\n");
  327.         unlock_listaccess();
  328.         return 0; 
  329.       }
  330.       if(dmsdos_read_cluster(dir->i_sb,clusterd,cluster,cvfnr))
  331.       { printk("DMSDOS: ioctl: D_READ: read_cluster failed!\n");
  332.         rwlist[rlist].flag=D_EMPTY;
  333.         unlock_listaccess();
  334.         FREE(clusterd);
  335.         return 0;   
  336.       }
  337.       rwlist[rlist].flag=D_IN_D_ACTION;
  338.       put_fs_long(rlist,idata);
  339.       put_fs_long(length,idata+4);
  340.       put_fs_long(rwlist[rlist].method,idata+8);
  341.       memcpy_tofs(idata+12,clusterd,length);
  342.       unlock_listaccess();
  343.       FREE(clusterd);
  344.       return 1;
  345.     case DMSDOS_D_WRITE:
  346.       if(current->euid!=0)return -EPERM;
  347.       lock_listaccess();
  348.       plist=get_fs_long(idata);
  349.       if(rwlist[plist].flag==D_OVERWRITTEN)rwlist[plist].flag=D_EMPTY;
  350.       if(rwlist[plist].flag!=D_IN_D_ACTION)
  351.       { /*printk("DMSDOS: D_WRITE: Entry not in action, flag=%d cluster=%d cvf=%d\n",
  352.                rwlist[plist].flag,rwlist[plist].clusternr,rwlist[plist].cvfnr+1);
  353.         */
  354.         unlock_listaccess();
  355.         return 0;
  356.       }
  357.       sectors=get_fs_long(idata+4);
  358.       if(sectors==0)
  359.       { /* data were uncompressible */
  360.         rwlist[plist].flag=D_EMPTY;
  361.         unlock_listaccess();
  362.         return 0;
  363.       }
  364.       /* check that cluster is used */
  365.       dbl_mdfat_value(dir->i_sb,rwlist[plist].clusternr,rwlist[plist].cvfnr,
  366.                       NULL,&mde);
  367.       if((mde.flags&3)!=3)
  368.       { rwlist[plist].flag=D_EMPTY;  /* remove - it's garbage */
  369.         /*printk("DMSDOS: D_WRITE: removing garbage entry cluster=%d cvf=%d\n",
  370.                rwlist[plist].clusternr,rwlist[plist].cvfnr+1);*/
  371.         unlock_listaccess();
  372.         return 0;
  373.       }
  374.       clusterd=MALLOC(sectors*SECTOR_SIZE);
  375.       if(clusterd==NULL)
  376.       { printk("DMSDOS: ioctl: D_WRITE: no memory!\n");
  377.         rwlist[plist].flag=D_EMPTY;
  378.         unlock_listaccess();
  379.         return 0;
  380.       }
  381.       length=rwlist[plist].length;
  382.       cluster=rwlist[plist].clusternr;
  383.       cvfnr=rwlist[plist].cvfnr;
  384.       memcpy_fromfs(clusterd,idata+12,sectors*SECTOR_SIZE);
  385.       dmsdos_write_cluster(dir->i_sb,clusterd,length,cluster,0,cvfnr,
  386.                            -sectors); /* ucflag < 0 means raw write */
  387.       rwlist[plist].flag=D_EMPTY;
  388.       unlock_listaccess();
  389.       FREE(clusterd);
  390.       return 0;
  391.     case DMSDOS_D_EXIT:
  392.       if(current->euid!=0)return -EPERM;
  393.       /* meldet dmsdosd ab */
  394.       daemon_present=0;
  395.       /*printk("DMSDOS: D_EXIT\n");*/
  396.       return 0;
  397.     case DMSDOS_MOVEBACK:
  398.       if(current->euid!=0)return -EPERM;
  399.       return moveback(dir->i_sb,data,cvfnr);
  400.     case DMSDOS_SET_MAXCLUSTER:
  401.       if(current->euid!=0)return -EPERM;
  402.       return set_maxcluster(dir->i_sb,data,cvfnr);      
  403.     default:
  404.       return -EINVAL;
  405.   }    
  406.     
  407. }
  408.  
  409. int try_daemon(int clusternr, int cvfnr, int length, int method)
  410. { int i;
  411.  
  412.   if(daemon_present==0)return 0;
  413.   
  414.   lock_listaccess();
  415.   
  416.   /* check list for existing entry and mark it as overwritten */
  417.   for(i=0;i<LISTSIZE;++i)
  418.   { if(rwlist[i].clusternr==clusternr&&rwlist[i].cvfnr==cvfnr)
  419.     {
  420.       if(rwlist[i].flag==D_IN_D_ACTION){rwlist[i].flag=D_OVERWRITTEN;break;}
  421.       if(rwlist[i].flag==D_VALID){rwlist[i].flag=D_EMPTY;break;}
  422.     }
  423.   }
  424.   
  425.   /* find empty slot in list */
  426.   for(i=LISTSIZE;i>0;--i)
  427.   { if(rwlist[wlist].flag==D_EMPTY) goto w_found;
  428.     wlist=(wlist+1)&(LISTSIZE-1);
  429.   }
  430.   /*this is commented out because it will fill the log _very_ fast...*/
  431.   /*printk("DMSDOS: try_daemon: no empty slot found.");*/
  432.   unlock_listaccess();
  433.   return 0;
  434.   
  435.  w_found:
  436.   rwlist[wlist].clusternr=clusternr;
  437.   rwlist[wlist].cvfnr=cvfnr;
  438.   rwlist[wlist].length=length;
  439.   rwlist[wlist].method=method;
  440.   rwlist[wlist].flag=D_VALID;
  441.   unlock_listaccess();
  442.   return 1;
  443. }
  444.  
  445. void clear_list_cvfnr(int cvfnr)
  446. { int i;
  447.  
  448.   lock_listaccess();
  449.   for(i=0;i<LISTSIZE;++i)
  450.   { if(rwlist[i].cvfnr==cvfnr)rwlist[i].flag=D_EMPTY;
  451.   }
  452.   unlock_listaccess();
  453. }
  454.  
  455. void clear_list(void)
  456. { int i;
  457.  
  458.   lock_listaccess();
  459.   for(i=0;i<LISTSIZE;++i)rwlist[i].flag=D_EMPTY;
  460.   unlock_listaccess();
  461. }
  462.